using System;
using System.IO;
using System.Reflection;
using System.Windows;
using Autodesk.Revit.UI;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json.Linq;
using RevitCopilot.MCPServer.Commands;

namespace RevitCopilot.Services;

// 执行命令服务，通过外部事件处理器动态执行命令
// 外部事件的UIApplication参数不是由开发者手动实例化的，而是由Revit的事件调度系统自动传入的
// Revit会不时地检查是否有外部事件发信号Raise，如果有就会调用外部事件相应的Execute()函数。
public class ExecCommandService : IExternalEventHandler
{
    private readonly ILogger<ExecCommandService> _logger;
    public JObject Parameters { get; set; } = new JObject();
    public string RequestId { get; set; } = string.Empty;
    public string CommandName { get; set; } = string.Empty;
    public string Result { get; private set; } = string.Empty;

    // 命令执行完成事件，参数为请求ID和执行结果
    public event Action<string, string> CommandExecuted;

    public ExecCommandService(ILogger<ExecCommandService> logger)
    {
        _logger = logger;
    }
    public void Execute(UIApplication app)
    {   //在具体的Command中需要抛出异常
        try
        {
            _logger.LogInformation("开始执行命令: {CommandName}", CommandName);
            // 加载程序集，当前项目引用了其他项目，dll生成在同一目录下
            // 获取当前插件 DLL 的路径
            string pluginPath = Assembly.GetExecutingAssembly().Location;
            string pluginDirectory = Path.GetDirectoryName(pluginPath);
            Assembly externalAssembly = Assembly.LoadFrom(Path.Combine(pluginDirectory, "RevitCopilot.Commands.dll"));
            // 获取类型DeleteElements => DeleteElementsCommand
            string fullTypeName = $"RevitCopilot.Commands.{CommandName}Command";
            Type? commandType = externalAssembly.GetType(fullTypeName);
            if (commandType == null)
            {
                _logger.LogError("找不到命令类型: {FullTypeName}", fullTypeName);
                Result = $"错误: 找不到命令类型 {fullTypeName}";
                return;
            }
            // 获取Execute方法
            MethodInfo? method = commandType.GetMethod("Execute", BindingFlags.Instance | BindingFlags.Public);
            if (method == null)
            {
                _logger.LogError("找不到Execute方法: {CommandType}", commandType.FullName);
                Result = $"错误: 找不到Execute方法 {commandType.FullName}";
                return;
            }
            // 创建命令实例，将UIApplication传入
            object[] constructorArgs = new object[] { app };
            object? commandInstance = Activator.CreateInstance(commandType, constructorArgs);

            if (commandInstance == null)
            {
                _logger.LogError("无法创建命令实例: {CommandType}", commandType.FullName);
                Result = $"错误: 无法创建命令实例 {commandType.FullName}";
                return;
            }
            // 执行命令并获取返回值
            object? result = method.Invoke(commandInstance, new object[] { Parameters, RequestId });
            Result = result?.ToString() ?? string.Empty;
            _logger.LogInformation("命令执行完成: {CommandName}, 结果: {Result}", CommandName, Result);

            // 触发命令执行完成事件，通过socket连接发送响应给MCP Tool
            CommandExecuted?.Invoke(RequestId, Result);
        }
        catch (Exception ex)
        {
            string errorMessage = $"执行命令失败: {ex.Message}";
            _logger.LogError(ex, "执行命令失败: {CommandName}", CommandName);
            Result = errorMessage;

            // 即使发生异常也触发命令执行完成事件，传递错误信息
            CommandExecuted?.Invoke(RequestId, Result);
        }
    }
    public string GetName() => "RevitCopilot";
}